package com.zj.common.fragment

import android.app.Activity
import android.content.Intent
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.databinding.DataBindingUtil
import androidx.databinding.ViewDataBinding
import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.ViewModelStoreOwner
import com.zj.common.listener.IBaseView
import com.zj.common.viewmodel.BaseViewModel
import java.lang.reflect.ParameterizedType

abstract class BaseFragment<VM : BaseViewModel, VDB : ViewDataBinding> : Fragment(), IBaseView<VM> {

    protected lateinit var binding: VDB
    protected val viewModel: VM by lazy {
        createViewModel()
    }

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        binding = DataBindingUtil.inflate(inflater, layoutId(), container, false)
        return binding.root
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        lifecycle.addObserver(viewModel)
        binding.setVariable(variableId(), viewModel)
        initData(savedInstanceState)
        viewModel.apply {
            activityEvent.observe(requireActivity()) {
                val activity = it["activity"] as Class<out Activity>
                val bundle = it["bundle"]
                goActivity(activity, bundle as Bundle?)
            }
        }
    }

    override fun createViewModel(): VM {
        return obtainViewModel(vMClass)
    }

    private val vMClass: Class<VM>
        get() {
            var cls: Class<*>? = javaClass
            var vmClass: Class<VM>? = null
            while (vmClass == null && cls != null) {
                vmClass = getVMClass(cls) as Class<VM>?
                cls = cls.superclass
            }
            if (vmClass == null) {
                vmClass = BaseViewModel::class.java as Class<VM>
            }
            return vmClass
        }

    private fun getVMClass(cls: Class<*>): Class<*>? {
        val type = cls.genericSuperclass
        if (type is ParameterizedType) {
            val types = type.actualTypeArguments
            for (t in types) {
                if (t is Class<*>) {
                    if (BaseViewModel::class.java.isAssignableFrom(t)) {
                        return t
                    }
                } else if (t is ParameterizedType) {
                    val rawType = t.rawType
                    if (rawType is Class<*>) {
                        if (BaseViewModel::class.java.isAssignableFrom(rawType)) {
                            return rawType
                        }
                    }
                }
            }
        }
        return null
    }

    private fun obtainViewModel(tClass: Class<VM>): VM {
        return createViewModelProvider(this).get(tClass)
    }

    /**
     * 创建 [ViewModelProvider]
     *
     * @param owner ViewModelStoreOwner实例对象
     * @return 返回实例
     */
    private fun createViewModelProvider(owner: ViewModelStoreOwner): ViewModelProvider {
        return ViewModelProvider(
            owner,
            ViewModelProvider.AndroidViewModelFactory.getInstance(requireActivity().application)
        )
    }

    override fun isTranslucent(): Boolean {
        return true
    }

    private fun goActivity(activity: Class<out Activity>, bundle: Bundle? = null) {
        val intent = Intent(requireActivity(), activity)
        if (bundle != null) {
            intent.putExtras(bundle)
        }
        startActivity(intent)
    }

    override fun onDestroy() {
        binding.unbind()
        lifecycle.removeObserver(viewModel)
        super.onDestroy()
    }
}